"""
Case Type   : 资源池化
Case Name   : 资源池化场景下, 进行备节点CM心跳故障测试
Create At   : 2024-11-29
Owner       : hejiuhuan
Description :
    1、查看集群状态 cm_ctl query -Cv
    2、指定数据库主节点的cm_server为主cms
    3、备节点1注入CM心跳故障
    4、查看集群状态 cm_ctl query -Cvpid
    5、备节点1恢复正常
    6、查看集群状态 cm_ctl query -Cvpid
    7、恢复集群原始状态
Expect      :
    1、集群状态正常, 数据库节点状态正常
    2、指定数据库主节点的cm_server为主cms成功
    3、构建备节点1CM心跳故障成功
    4、备节点1cms为down状态
    5、备节点1恢复正常成功
    6、集群状态正常, 数据库节点状态正常
    7、恢复集群原始状态成功
History     :
    1、2024-11-29 创建
    2、2025-07-09 修改为1p1s环境执行用例
"""

import os
import unittest
import time

from testcase.utils.ComThread import ComThread
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import macro
from yat.test import Node
from testcase.utils.Common import Common

Primary_SH = CommonSH('PrimaryDbUser')
Standby1_ROOTSH = CommonSH('Standby1Root')

@unittest.skipIf(1 == Primary_SH.get_node_num(), '单机环境不执行')
class SharedStorage(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.s1Root = Node('Standby1Root')
        self.constant = Constant()

    def test_shared_storage(self):
        text = '-----step1:查看集群状态; expect:集群状态正常,若不正常则重启集群重新查看-----'
        self.log.info(text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        if "can't connect to cm_server" in status:
            stopdn = Primary_SH.exec_cm_ctl('stop')
            self.log.info(stopdn)
            status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
            startdn = Primary_SH.exec_cm_ctl('start')
            self.log.info(startdn)
            self.assertIn(self.constant.cm_start_success_msg, startdn,
                    '拉起集群失败')
            status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
            self.log.info(status)
        else:
            self.log.info(status + "集群状态正常")
        self.log.info(status)
        self.assertIn(self.constant.CLUSTER_NORMAL_MSG, status, '执行失败' + text)

        text = '-----step2:指定数据库主节点的cm_server为主节点; expect:指定成功-----'
        self.log.info(text)
        set_cms_primary = Primary_SH.exec_cm_ctl(mode='set', param='--cmsPromoteMode=PRIMARY_F -I 1')
        self.log.info(set_cms_primary)
        self.assertIn('successfully', set_cms_primary, '执行失败' + text)

        text = '-----step3:备节点1构建CM心跳故障; expect:构建成功-----'
        self.log.info(text)
        res = Primary_SH.exec_cmd_under_user("lsof -i -n -P | grep cm_server | cut -d':' -f2 | cut -d'(' -f1")
        self.log.info(res)
        cmsport = res.splitlines()[0]
        s1_host_ip = self.s1Root.db_host
        # 使用iptables进行备节点CM心跳故障构建
        Standby1_ROOTSH.exec_iptables(host_ip=s1_host_ip, cms_port=cmsport, rule=True)
        time.sleep(10)

        text = '-----step4:查看集群状态; expect:查询成功-----'
        self.log.info(text)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cvpid')
        self.log.info(status)
        self.assertIn(self.constant.CLUSTER_NORMAL_MSG, status, '执行失败' + text)
        self.assertIn('/cm_server Primary', status, '执行失败' + text)
        self.assertIn('/cm_server Down', status, '执行失败' + text)

    def tearDown(self):
        text = '-----step5:故障恢复; expect:恢复成功-----'
        self.log.info(text)
        time.sleep(50)
        res = Primary_SH.exec_cmd_under_user("lsof -i -n -P | grep cm_server | cut -d':' -f2 | cut -d'(' -f1")
        self.log.info(res)
        cmsport = res.splitlines()[0]
        s1_host_ip = self.s1Root.db_host
        Standby1_ROOTSH.exec_iptables(host_ip=s1_host_ip, cms_port=cmsport, rule=False)

        text = '-----step6:查看集群状态; expect:查询成功,集群状态正常-----'
        self.log.info(text)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        status = Primary_SH.check_cluster_core_status(status, wait_times=600)
        self.log.info(status)
        time.sleep(10)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cvpid')
        self.log.info(status)
        self.assertIn(self.constant.CLUSTER_NORMAL_MSG, status, '执行失败' + text)
        self.assertTrue('/cm_server Down' not in status, '执行失败' + text)

        text = '-----step7:恢复环境为初始集群状态; expect:成功-----'
        self.log.info(text)

        status = Primary_SH.exec_cm_ctl(mode='stop')
        self.log.info(status)
        self.assertIn(self.constant.cm_stop_success_msg, status, '执行失败' + text)

        status = Primary_SH.exec_cm_ctl(mode='start')
        self.log.info(status)
        self.assertIn(self.constant.cm_start_success_msg, status, '执行失败' + text)

        recovery_switchover = Primary_SH.exec_cm_ctl(mode='switchover', param='-a')
        self.log.info(recovery_switchover)
        self.assertIn(self.constant.cm_switchover_success_msg, recovery_switchover,
                      '执行失败' + text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('P Primary Normal',
                      status.splitlines()[-1].split('|')[0].split('6001')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                      status.splitlines()[-1].split('|')[1].split('6002')[-1],
                      '执行失败' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')

